package cn.ekuma.epos.order;

import javax.swing.JPanel;
import java.awt.BorderLayout;

import javax.swing.AbstractListModel;
import javax.swing.JTextPane;
import javax.swing.JList;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.swing.ListSelectionModel;
import cn.ekuma.data.ui.swing.AbstractDAOJEditor;
import cn.ekuma.epos.businesslogic.RoleUtil;
import cn.ekuma.epos.datalogic.I_DataLogicCustomers;
import cn.ekuma.epos.datalogic.I_DataLogicERP;
import cn.ekuma.epos.datalogic.I_DataLogicSystem;

import com.openbravo.bean.AppUser;
import com.openbravo.bean.erp.OrderRelation;
import com.openbravo.bean.erp.OrderType;
import com.openbravo.bean.erp.viewbean.FindOrdersInfo;
import com.openbravo.data.basic.BasicException;
import com.openbravo.data.user.DirtyManager;
import com.openbravo.format.Formats;

import com.openbravo.pos.base.AppLocal;
import com.openbravo.pos.base.AppView;
import javax.swing.JButton;

import org.ofsm.IEvent;
import org.ofsm.impl.FileFiniteStateMachine;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.ByteArrayInputStream;
import javax.swing.JLabel;
import java.awt.FlowLayout;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class JOrderRelationEditor extends AbstractDAOJEditor<OrderRelation> {
	
	private JTextPane textPane;
	private JList jEventList;
	private AppView m_App;
	private JButton btnNewButton;
	private JOrderInfoViewPanel jOrderInfoViewPanel;
	FileFiniteStateMachine stateMachine;
	private I_DataLogicERP dlSales;
	private I_DataLogicSystem dlSystem;
	private List ableEvents;
	private JPanel panel_1;
	private JPanel panel_2;
	private JLabel lblNewLabel;
	private JTextField textField;
	private JLabel lblNewLabel_1;
	private JTextField debt;
	I_DataLogicCustomers dlCustomers;

	public JOrderRelationEditor(AppView app,final DirtyManager dirty,I_DataLogicERP dlSales,I_DataLogicSystem dlSystem,I_DataLogicCustomers dlCustomers) {
		super(dirty);
		this.m_App=app;
		this.dlSales = dlSales;
		this.dlSystem = dlSystem;
		this.dlCustomers=dlCustomers;
		initComponents();
		stateMachine=new FileFiniteStateMachine();
		textPane.getDocument().addDocumentListener(dirty);
		debt.getDocument().addDocumentListener(dirty);
		jEventList.addListSelectionListener(new ListSelectionListener(){
			@Override
			public void valueChanged(ListSelectionEvent e) {
				IEvent selectEvent=(IEvent) jEventList.getSelectedValue();
				if(selectEvent!=null){
				   stateMachine.fireEvent(selectEvent);
				   textField.setText(stateMachine.getCurrentState().getName());
				   obj.setAfterState(textField.getText());
				   dirty.setDirty(true);
				}
			}
		});
		
	}

	private void initComponents() {
	    setLayout(new BorderLayout(0, 0));
		
		JPanel panel = new JPanel();
		add(panel, BorderLayout.SOUTH);
		panel.setLayout(new BorderLayout(0, 0));
		
		jEventList = new JList();
		jEventList.setPreferredSize(new Dimension(150, 100));
		jEventList.setBorder(new TitledBorder(null, AppLocal.getIntString("orderState.ableEvents"), TitledBorder.LEADING, TitledBorder.TOP, null, null));
		jEventList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		panel.add(jEventList, BorderLayout.EAST);
		
	    textPane = new JTextPane();
	    panel.add(textPane);
	    textPane.setBorder(new TitledBorder(null, AppLocal.getIntString("label.order.memo"), TitledBorder.LEADING, TitledBorder.TOP, null, null));
		
		panel_1 = new JPanel();
		add(panel_1, BorderLayout.CENTER);
		panel_1.setLayout(new BorderLayout(0, 0));
		jOrderInfoViewPanel=new JOrderInfoViewPanel();
		panel_1.add(jOrderInfoViewPanel, BorderLayout.NORTH);
		
		panel_2 = new JPanel();
		panel_2.setPreferredSize(new Dimension(10, 40));
		FlowLayout flowLayout = (FlowLayout) panel_2.getLayout();
		flowLayout.setAlignment(FlowLayout.LEFT);
		panel_1.add(panel_2, BorderLayout.SOUTH);
		
		lblNewLabel = new JLabel(AppLocal.getIntString("label.orderStates"));
		lblNewLabel.setPreferredSize(new Dimension(80, 20));
		panel_2.add(lblNewLabel);
		
		textField = new JTextField();
		textField.setEditable(false);
		textField.setRequestFocusEnabled(false);
		panel_2.add(textField);
		textField.setColumns(25);
		
		lblNewLabel_1 = new JLabel(AppLocal.getIntString("label.curdebt"));
		lblNewLabel_1.setPreferredSize(new Dimension(80, 15));
		panel_2.add(lblNewLabel_1);
		
		debt = new JTextField();
		debt.setEditable(false);
		panel_2.add(debt);
		debt.setColumns(15);

		btnNewButton = new JButton();
		add(btnNewButton, BorderLayout.NORTH);
		btnNewButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/com/openbravo/images/search.png")));
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				seachOrder();
			}
		});
		btnNewButton.setAlignmentY(0.0f);
		btnNewButton.setPreferredSize(new Dimension(100, 23));
	}

	@Override
	public void refresh() {
	}

	public void seachOrder(){
		JOrdersFinder orderFinder = JOrdersFinder.getOrderFinder(this, m_App,dlSales,dlCustomers);
		orderFinder.setVisible(true);
		if (orderFinder.getSelectedOrder() != null) {
			obj.setRelOrderInfo(orderFinder.getSelectedOrder());
			obj.setRefId(orderFinder.getSelectedOrder().getId());
			obj.setBeforState(orderFinder.getSelectedOrder().getCurrentState());
			try {
				initStateMachine(obj.getRelOrderInfo());
				ableEvents = RoleUtil.filterUserOrderTypeEvents((AppUser) m_App.getAppUserView().getUser(),obj.getRelOrderInfo().getDefineTypeId(),stateMachine.getTransitionEventByCurrentState());
			} catch (BasicException e) {
				ableEvents=new ArrayList();
			}
		}else{
			obj.setRelOrderInfo(null);
			obj.setRefId(null);
			ableEvents=new ArrayList();
		}
		jEventList.setModel(new AbstractListModel() {
            public int getSize() {
                return ableEvents.size();
            }

            public Object getElementAt(int index) {
                return ableEvents.get(index);
            }
        });
		
		jOrderInfoViewPanel.updateUI(obj.getRelOrderInfo());
		if(obj.getRelOrderInfo().getDebt()>0)
			debt.setEditable(true);
		else
			debt.setEditable(false);
		debt.setText(null);
		dirty.setDirty(true);
	}
	
	@Override
	public OrderRelation createNew(Properties prop) {
		jOrderInfoViewPanel.updateUI(null);
		ableEvents=new ArrayList();
		jEventList.setModel(new AbstractListModel() {
            public int getSize() {
                return ableEvents.size();
            }

            public Object getElementAt(int index) {
                return ableEvents.get(index);
            }
        });
		return new OrderRelation();
	}

	@Override
	public void rebuild(OrderRelation obj) throws BasicException {
		obj.setMemo(textPane.getText());
		obj.setAfterState(textField.getText());
		obj.setCash((Double) Formats.CURRENCY.parseValue(debt.getText(), 0.0));
	}

	@Override
	public void updateUI(boolean editAble, int state) {
		textPane.setText(obj.getMemo());
		textField.setText(obj.getAfterState());
		debt.setText(Formats.CURRENCY.formatValue(obj.getCash()));
		textPane.setEditable(editAble);
		jEventList.setEnabled(editAble);
		debt.setEditable(editAble);
	}

	@Override
	public Class getEditClass() {
		return OrderRelation.class;
	}

	@Override
	public String validator(OrderRelation obj) {
		if(obj.getRelOrderInfo()==null)
			return "order must selected";
		return super.validator(obj);
	}

	
	private void initStateMachine(FindOrdersInfo order) throws BasicException{
	   OrderType orderType=(OrderType) dlSales.findByStringId(OrderType.class, order.getDefineTypeId());
       String stateMachineName = orderType.getStateMachine();
       String currentState = order.getCurrentState();
        if (stateMachineName == null || stateMachineName.isEmpty()) {
        } else {
            byte[] bf = dlSystem.getResourceAsBinary(stateMachineName);
            if (bf != null) {
                ByteArrayInputStream btStream = new ByteArrayInputStream(bf);
                try {
                    stateMachine.init(btStream);
                    stateMachine.setCurrentState(currentState);
                } catch (Exception ex) {
                   throw new BasicException(ex);
                }
            }
        }
    }
}
